"""
消息系统路由
"""
from fastapi import APIRouter, Depends, HTTPException, status, Query, WebSocket, WebSocketDisconnect
from sqlalchemy.orm import Session
from typing import List, Optional
from datetime import datetime
import json

from database import get_db
from auth import get_current_active_user
from models import Message, User, Conversation, ConversationParticipant
from schemas import MessageResponse, MessageCreate, BaseResponse, PaginatedResponse

router = APIRouter()

# WebSocket连接管理器
class ConnectionManager:
    def __init__(self):
        self.active_connections: dict[int, WebSocket] = {}

    async def connect(self, websocket: WebSocket, user_id: int):
        await websocket.accept()
        self.active_connections[user_id] = websocket

    def disconnect(self, user_id: int):
        if user_id in self.active_connections:
            del self.active_connections[user_id]

    async def send_personal_message(self, message: str, user_id: int):
        if user_id in self.active_connections:
            await self.active_connections[user_id].send_text(message)

    async def broadcast(self, message: str, exclude_user_id: Optional[int] = None):
        for user_id, connection in self.active_connections.items():
            if user_id != exclude_user_id:
                await connection.send_text(message)

manager = ConnectionManager()

@router.websocket("/ws/{user_id}")
async def websocket_endpoint(websocket: WebSocket, user_id: int, db: Session = Depends(get_db)):
    """WebSocket连接端点"""
    await manager.connect(websocket, user_id)
    try:
        while True:
            data = await websocket.receive_text()
            # 处理接收到的消息
            message_data = json.loads(data)
            
            # 保存消息到数据库
            message = Message(
                conversation_id=message_data['conversation_id'],
                sender_id=user_id,
                content=message_data['content'],
                message_type=message_data.get('message_type', 'text')
            )
            db.add(message)
            db.commit()
            db.refresh(message)
            
            # 发送消息给对话参与者
            conversation = db.query(Conversation).filter(Conversation.id == message_data['conversation_id']).first()
            if conversation:
                participants = db.query(ConversationParticipant).filter(
                    ConversationParticipant.conversation_id == conversation.id
                ).all()
                
                for participant in participants:
                    if participant.user_id != user_id:
                        await manager.send_personal_message(
                            json.dumps({
                                'type': 'message',
                                'data': {
                                    'id': message.id,
                                    'conversation_id': message.conversation_id,
                                    'sender_id': message.sender_id,
                                    'content': message.content,
                                    'message_type': message.message_type,
                                    'created_at': message.created_at.isoformat()
                                }
                            }),
                            participant.user_id
                        )
    
    except WebSocketDisconnect:
        manager.disconnect(user_id)

@router.post("/conversations/", response_model=BaseResponse)
async def create_conversation(
    target_user_id: int,
    db: Session = Depends(get_db),
    current_user: User = Depends(get_current_active_user)
):
    """创建对话"""
    # 检查目标用户是否存在
    target_user = db.query(User).filter(User.id == target_user_id).first()
    if not target_user:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail="目标用户不存在"
        )
    
    # 检查是否已存在对话
    existing_conversation = db.query(Conversation).join(ConversationParticipant).filter(
        ConversationParticipant.user_id.in_([current_user.id, target_user_id])
    ).group_by(Conversation.id).having(
        db.func.count(ConversationParticipant.user_id) == 2
    ).first()
    
    if existing_conversation:
        return BaseResponse(message="对话已存在", data={"conversation_id": existing_conversation.id})
    
    # 创建新对话
    conversation = Conversation()
    db.add(conversation)
    db.commit()
    db.refresh(conversation)
    
    # 添加参与者
    participants = [
        ConversationParticipant(conversation_id=conversation.id, user_id=current_user.id),
        ConversationParticipant(conversation_id=conversation.id, user_id=target_user_id)
    ]
    db.add_all(participants)
    db.commit()
    
    return BaseResponse(message="对话创建成功", data={"conversation_id": conversation.id})

@router.get("/conversations", response_model=PaginatedResponse)
async def get_conversations(
    page: int = Query(1, ge=1, description="页码"),
    size: int = Query(20, ge=1, le=100, description="每页数量"),
    db: Session = Depends(get_db),
    current_user: User = Depends(get_current_active_user)
):
    """获取对话列表"""
    # 获取用户参与的对话
    query = db.query(Conversation).join(ConversationParticipant).filter(
        ConversationParticipant.user_id == current_user.id
    ).order_by(Conversation.updated_at.desc())
    
    total = query.count()
    conversations = query.offset((page - 1) * size).limit(size).all()
    
    # 获取每个对话的最新消息和对方用户信息
    result = []
    for conversation in conversations:
        # 获取对方用户
        other_participant = db.query(ConversationParticipant).filter(
            ConversationParticipant.conversation_id == conversation.id,
            ConversationParticipant.user_id != current_user.id
        ).first()
        
        other_user = db.query(User).filter(User.id == other_participant.user_id).first() if other_participant else None
        
        # 获取最新消息
        latest_message = db.query(Message).filter(
            Message.conversation_id == conversation.id
        ).order_by(Message.created_at.desc()).first()
        
        result.append({
            'id': conversation.id,
            'other_user': other_user,
            'latest_message': latest_message,
            'unread_count': 0  # 可以添加未读消息计数逻辑
        })
    
    return PaginatedResponse(
        items=result,
        total=total,
        page=page,
        size=size,
        pages=(total + size - 1) // size
    )

@router.get("/conversations/{conversation_id}/messages", response_model=PaginatedResponse)
async def get_conversation_messages(
    conversation_id: int,
    page: int = Query(1, ge=1, description="页码"),
    size: int = Query(20, ge=1, le=100, description="每页数量"),
    db: Session = Depends(get_db),
    current_user: User = Depends(get_current_active_user)
):
    """获取对话消息"""
    # 检查用户是否参与此对话
    participant = db.query(ConversationParticipant).filter(
        ConversationParticipant.conversation_id == conversation_id,
        ConversationParticipant.user_id == current_user.id
    ).first()
    
    if not participant:
        raise HTTPException(
            status_code=status.HTTP_403_FORBIDDEN,
            detail="无权查看此对话"
        )
    
    # 获取消息
    query = db.query(Message).filter(
        Message.conversation_id == conversation_id
    ).order_by(Message.created_at.desc())
    
    total = query.count()
    messages = query.offset((page - 1) * size).limit(size).all()
    
    return PaginatedResponse(
        items=messages,
        total=total,
        page=page,
        size=size,
        pages=(total + size - 1) // size
    )

@router.post("/conversations/{conversation_id}/messages", response_model=MessageResponse)
async def send_message(
    conversation_id: int,
    message_data: MessageCreate,
    db: Session = Depends(get_db),
    current_user: User = Depends(get_current_active_user)
):
    """发送消息"""
    # 检查用户是否参与此对话
    participant = db.query(ConversationParticipant).filter(
        ConversationParticipant.conversation_id == conversation_id,
        ConversationParticipant.user_id == current_user.id
    ).first()
    
    if not participant:
        raise HTTPException(
            status_code=status.HTTP_403_FORBIDDEN,
            detail="无权在此对话发送消息"
        )
    
    # 创建消息
    message = Message(
        conversation_id=conversation_id,
        sender_id=current_user.id,
        content=message_data.content,
        message_type=message_data.message_type
    )
    
    db.add(message)
    db.commit()
    db.refresh(message)
    
    # 更新对话时间
    conversation = db.query(Conversation).filter(Conversation.id == conversation_id).first()
    conversation.updated_at = datetime.utcnow()
    db.commit()
    
    return message

@router.put("/messages/{message_id}/read", response_model=BaseResponse)
async def mark_message_read(
    message_id: int,
    db: Session = Depends(get_db),
    current_user: User = Depends(get_current_active_user)
):
    """标记消息为已读"""
    message = db.query(Message).filter(Message.id == message_id).first()
    if not message:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail="消息不存在"
        )
    
    # 检查用户是否参与此对话
    participant = db.query(ConversationParticipant).filter(
        ConversationParticipant.conversation_id == message.conversation_id,
        ConversationParticipant.user_id == current_user.id
    ).first()
    
    if not participant:
        raise HTTPException(
            status_code=status.HTTP_403_FORBIDDEN,
            detail="无权操作此消息"
        )
    
    # 标记消息为已读（这里可以扩展为记录已读状态）
    # message.is_read = True
    # db.commit()
    
    return BaseResponse(message="消息已标记为已读")

@router.delete("/messages/{message_id}", response_model=BaseResponse)
async def delete_message(
    message_id: int,
    db: Session = Depends(get_db),
    current_user: User = Depends(get_current_active_user)
):
    """删除消息"""
    message = db.query(Message).filter(Message.id == message_id).first()
    if not message:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail="消息不存在"
        )
    
    # 检查权限（只能删除自己的消息）
    if message.sender_id != current_user.id:
        raise HTTPException(
            status_code=status.HTTP_403_FORBIDDEN,
            detail="无权删除此消息"
        )
    
    # 软删除消息
    message.is_deleted = True
    db.commit()
    
    return BaseResponse(message="消息删除成功")

@router.get("/{other_user_id}", response_model=BaseResponse)
async def get_or_create_conversation_with_user(
    other_user_id: int,
    db: Session = Depends(get_db),
    current_user: User = Depends(get_current_active_user)
):
    """与特定用户创建或获取对话，并返回对话消息"""
    try:
        # 检查目标用户是否存在
        target_user = db.query(User).filter(User.id == other_user_id).first()
        if not target_user:
            raise HTTPException(
                status_code=status.HTTP_404_NOT_FOUND,
                detail="用户不存在"
            )
        
        # 不能与自己聊天
        if other_user_id == current_user.id:
            raise HTTPException(
                status_code=status.HTTP_400_BAD_REQUEST,
                detail="不能与自己聊天"
            )
        
        # 查找现有对话
        conversation = db.query(Conversation).join(ConversationParticipant).filter(
            ConversationParticipant.user_id == current_user.id
        ).first()
        
        # 如果没有找到对话，创建一个新对话
        if not conversation:
            conversation = Conversation()
            db.add(conversation)
            db.commit()
            db.refresh(conversation)
            
            # 添加参与者
            participants = [
                ConversationParticipant(conversation_id=conversation.id, user_id=current_user.id),
                ConversationParticipant(conversation_id=conversation.id, user_id=other_user_id)
            ]
            db.add_all(participants)
            db.commit()
            db.refresh(conversation)
        
        # 获取对话消息
        messages = db.query(Message).filter(
            Message.conversation_id == conversation.id
        ).order_by(Message.created_at.desc()).limit(50).all()
        
        # 获取对方用户信息
        other_user = target_user
        
        return BaseResponse(
            message="对话获取成功",
            data={
                "conversation": {
                    "id": conversation.id,
                    "user1_id": current_user.id,
                    "user2_id": other_user_id,
                    "created_at": conversation.created_at,
                    "updated_at": conversation.updated_at,
                    "other_user": {
                        "id": other_user.id,
                        "username": other_user.username,
                        "nickname": other_user.nickname,
                        "avatar_url": other_user.avatar_url
                    }
                },
                "messages": [
                    {
                        "id": msg.id,
                        "conversation_id": msg.conversation_id,
                        "sender_id": msg.sender_id,
                        "content": msg.content,
                        "message_type": msg.message_type,
                        "created_at": msg.created_at,
                        "is_read": msg.is_read
                    }
                    for msg in reversed(messages)
                ]
            }
        )
    except HTTPException:
        raise
    except Exception as e:
        print(f"获取对话失败: {e}")
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail="获取对话失败"
        )

@router.post("", response_model=MessageResponse)
async def send_message_to_user(
    message_data: MessageCreate,
    db: Session = Depends(get_db),
    current_user: User = Depends(get_current_active_user)
):
    """向特定用户发送消息"""
    try:
        other_user_id = message_data.receiver_id
        
        # 检查目标用户是否存在
        target_user = db.query(User).filter(User.id == other_user_id).first()
        if not target_user:
            raise HTTPException(
                status_code=status.HTTP_404_NOT_FOUND,
                detail="用户不存在"
            )
        
        # 不能给自己发消息
        if other_user_id == current_user.id:
            raise HTTPException(
                status_code=status.HTTP_400_BAD_REQUEST,
                detail="不能给自己发消息"
            )
        
        # 查找现有对话
        conversation = db.query(Conversation).join(ConversationParticipant).filter(
            ConversationParticipant.user_id == current_user.id
        ).first()
        
        # 如果没有找到对话，创建一个新对话
        if not conversation:
            conversation = Conversation()
            db.add(conversation)
            db.commit()
            db.refresh(conversation)
            
            # 添加参与者
            participants = [
                ConversationParticipant(conversation_id=conversation.id, user_id=current_user.id),
                ConversationParticipant(conversation_id=conversation.id, user_id=other_user_id)
            ]
            db.add_all(participants)
            db.commit()
        
        # 创建消息
        message = Message(
            conversation_id=conversation.id,
            sender_id=current_user.id,
            content=message_data.content,
            message_type=message_data.message_type
        )
        
        db.add(message)
        db.commit()
        db.refresh(message)
        
        # 更新对话时间
        conversation.updated_at = datetime.utcnow()
        db.commit()
        
        return message
        
    except HTTPException:
        raise
    except Exception as e:
        print(f"发送消息失败: {e}")
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail="发送消息失败"
        )

@router.put("/conversation/{conversation_id}/read", response_model=BaseResponse)
async def mark_conversation_read(
    conversation_id: int,
    db: Session = Depends(get_db),
    current_user: User = Depends(get_current_active_user)
):
    """标记对话消息为已读"""
    try:
        # 检查用户是否参与此对话
        participant = db.query(ConversationParticipant).filter(
            ConversationParticipant.conversation_id == conversation_id,
            ConversationParticipant.user_id == current_user.id
        ).first()
        
        if not participant:
            raise HTTPException(
                status_code=status.HTTP_403_FORBIDDEN,
                detail="无权操作此对话"
            )
        
        # 这里可以添加标记未读消息为已读的逻辑
        # 为了简化，暂时只返回成功消息
        return BaseResponse(message="对话已标记为已读")
        
    except HTTPException:
        raise
    except Exception as e:
        print(f"标记对话已读失败: {e}")
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail="标记对话已读失败"
        )